﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Keyboard = Microsoft.Xna.Framework.Input.Keyboard;
using Rectangle = Microsoft.Xna.Framework.Rectangle;
using Microsoft.Devices.Sensors;

namespace Tetris
{
    public partial class GamePage : PhoneApplicationPage
    {
        ContentManager contentManager;
        GameTimer timer;
        SpriteBatch spriteBatch;

        private Texture2D tetrisBackground, tetrisTextures;
        private SpriteFont font;
        private readonly Rectangle[] blockRectangles = new Rectangle[7];

        // Game
        private Board board;
        private Score score;
        private bool pause = false;

        private KeyboardState oldKeyboardState = Keyboard.GetState();

        private Accelerometer accelSensor;
        private Vector2 accelReadings;

        public GamePage()
        {
            InitializeComponent();

            // Get the content manager from the application
            contentManager = (Application.Current as App).Content;

            // Create a timer for this page
            timer = new GameTimer();
            timer.UpdateInterval = TimeSpan.FromTicks(333333);
            timer.Update += OnUpdate;
            timer.Draw += OnDraw;

            createSpriteRectangle();

            TouchPanel.EnabledGestures = GestureType.Tap | GestureType.Flick;

            accelSensor = new Accelerometer();
            accelSensor.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<AccelerometerReading>>(accelSensor_CurrentValueChanged);
            accelSensor.Start();
        }

        void accelSensor_CurrentValueChanged(object sender, SensorReadingEventArgs<AccelerometerReading> e)
        {
            accelReadings = new Vector2(e.SensorReading.Acceleration.X, -e.SensorReading.Acceleration.Y);
        }

        private void createSpriteRectangle()
        {
            // Create sprite rectangles for each figure in texture file
            // O figure
            blockRectangles[0] = new Rectangle(312, 0, 24, 24);
            // I figure
            blockRectangles[1] = new Rectangle(0, 24, 24, 24);
            // J figure
            blockRectangles[2] = new Rectangle(120, 0, 24, 24);
            // L figure
            blockRectangles[3] = new Rectangle(216, 24, 24, 24);
            // S figure
            blockRectangles[4] = new Rectangle(48, 96, 24, 24);
            // Z figure
            blockRectangles[5] = new Rectangle(240, 72, 24, 24);
            // T figure
            blockRectangles[6] = new Rectangle(144, 96, 24, 24);
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            // Set the sharing mode of the graphics device to turn on XNA rendering
            SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(true);

            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(SharedGraphicsDeviceManager.Current.GraphicsDevice);

            // Start the timer
            timer.Start();

            tetrisBackground = contentManager.Load<Texture2D>(@"background");
            tetrisTextures = contentManager.Load<Texture2D>(@"tetris");

            font = contentManager.Load<SpriteFont>(@"font");

            // Create game fields
            board = new Board(ref tetrisTextures, blockRectangles);
            score = new Score(font);

            base.OnNavigatedTo(e);
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            // Stop the timer
            timer.Stop();

            // Set the sharing mode of the graphics device to turn off XNA rendering
            SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(false);

            base.OnNavigatedFrom(e);
        }

        /// <summary>
        /// Allows the page to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        private void OnUpdate(object sender, GameTimerEventArgs e)
        {
            #region Keyboard
            KeyboardState keyboardState = Keyboard.GetState();

            // PAUSE
            bool pauseKey = (oldKeyboardState.IsKeyDown(Keys.P) &&
                (keyboardState.IsKeyUp(Keys.P)));

            oldKeyboardState = keyboardState;

            if (pauseKey)
                pause = !pause;

            if (!pause)
            {
                // Find dynamic figure position
                board.FindDynamicFigure();

                // Increase player score
                int lines = board.DestroyLines();
                if (lines > 0)
                {
                    score.Value += (int)((5.0f / 2.0f) * lines * (lines + 3));
                    board.Speed += 0.005f;
                }

                score.Level = (int)(10 * board.Speed);

                // Create new shape in game
                if (!board.CreateNewFigure())
                    GameOver();
                else
                {
                    // If left key is pressed
                    if (keyboardState.IsKeyDown(Keys.Left))
                        board.MoveFigureLeft();
                    // If right key is pressed
                    if (keyboardState.IsKeyDown(Keys.Right))
                        board.MoveFigureRight();
                    // If down key is pressed
                    if (keyboardState.IsKeyDown(Keys.Down))
                        board.MoveFigureDown();

                    // Rotate figure
                    if (keyboardState.IsKeyDown(Keys.Up) || keyboardState.IsKeyDown(Keys.Space))
                        board.RotateFigure();

                    // Moving figure
                    if (board.Movement >= 1)
                    {
                        board.Movement = 0;
                        board.MoveFigureDown();
                    }
                    else
                        board.Movement += board.Speed;
                }
            }
            #endregion Keyboard

            while (TouchPanel.IsGestureAvailable)
            {
                GestureSample gesture = TouchPanel.ReadGesture();
                switch (gesture.GestureType)
                {
                    case GestureType.Flick:
                        
                        break;
                    case GestureType.Tap:
                        board.RotateFigure();
                        break;
                }
            }

            if (accelReadings.Y > 0.5)
            {
                board.MoveFigureDown();
            }

            if (accelReadings.X > 0.2)
            {
                board.MoveFigureRight();
            }

            if (accelReadings.X < -0.2)
            {
                board.MoveFigureLeft();
            }
        }

        /// <summary>
        /// Allows the page to draw itself.
        /// </summary>
        private void OnDraw(object sender, GameTimerEventArgs e)
        {
            SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Color.CornflowerBlue);

            TimeSpan gameTime = new TimeSpan(e.ElapsedTime.Hours, e.ElapsedTime.Minutes, e.ElapsedTime.Seconds);

            spriteBatch.Begin();
            spriteBatch.Draw(tetrisBackground, Vector2.Zero, Color.White);
            board.Draw(spriteBatch);
            score.Draw(spriteBatch);
            spriteBatch.End();
        }

        private void GameOver()
        {
            if (score.Value > score.RecordScore)
            {
                score.RecordScore = score.Value;

                pause = true;

                // TODO: naprawic zapisywanie
                //Record record = new Record();
                //record.ShowDialog();

                //score.RecordPlayer = record.Player;

                //using (StreamWriter writer = File.CreateText("record.dat"))
                //{
                //    writer.WriteLine(score.RecordPlayer);
                //    writer.WriteLine(score.RecordScore);
                //}

                pause = false;
            }

            board.Initialize();
            score.Initialize();
        }
    }
}